import PlanAPI from '@/api/Plan';
import ProductAPI from '@/api/Product';
import {
  Box,
  DragAndDropProvider,
  DraggableItem,
  DragHandle,
  DroppableContainer,
  FieldCols,
  FieldEffect,
  FormSection,
  Icon,
  mapField,
  PopoverConfirm,
  useCall,
  useFormValue,
  useQueryValue,
  useReq,
  useSimpleMemo,
} from '@/components';
import { MAIN_RISK_TYPE } from '@/constants/options';
import { companyFields } from '@/constants/sharedFields';
import { SelectProduct } from '@/pages/components';
import { pathJoin } from '@/utils';
import { catchAndScrollFor } from '@/utils/fp';
import { Button, Form, message, Space, Spin, Table } from 'antd';
import React, { createContext, useContext, useEffect, useMemo, useRef } from 'react';

const FIELDS = [
  [
    'planCode',
    '计划编码',
    null,
    {
      required: true,
      getFieldProps: () => ({ readOnly: !!useQueryValue('planBusinessCode') }),
    },
  ],
  ['planName', '计划名称', null, { required: true }],
  ...companyFields,
].map(mapField);

const Context = createContext({ planBusinessCode: null, premiumAddType: null });

function RequestProducts() {
  const { form } = useContext(Context);
  const companyCode = useFormValue(form, 'companyCode');
  const selected = useFormValue(form, 'products', (v) => v?.map((t) => t.productCode) ?? []);
  const onSelect = useCall(async (prodList) => {
    let codes = prodList.map((v) => v.productCode);
    codes = codes.filter((k) => !selected.includes(k));
    if (!codes.length) return;
    const data = await ProductAPI.selectProductDetailList(selected.concat(codes));
    if (data?.data) {
      form.setFieldsValue({ products: data.data });
    }
  });

  const getList = useRef(() => form.getFieldValue('products')?.slice() ?? []).current;

  const tableProps = useMemo(
    () => ({
      components: {
        body: {
          row: DraggableItem,
        },
      },
      onRow: (row, index) => ({ row, index, key: row?.id ?? index }),
    }),
    [],
  );

  const config = useMemo(
    () => ({
      rowKey: 'id',
      itemComponent: 'tr',
      getDroppableKeys() {
        return getList().map((v) => v.id);
      },
      onDrop(rowCtx, currentIndex) {
        const prodList = getList();
        const [item] = prodList.splice(rowCtx.index, 1);
        prodList.splice(currentIndex, 0, item);
        form.setFieldsValue({ products: prodList });
      },
    }),
    [],
  );

  const columns = useMemo(
    () => [
      {
        key: 'rm',
        align: 'center',
        width: 64,
        render(col, row, index) {
          return (
            <PopoverConfirm
              onOk={() => {
                const prodList = getList();
                prodList.splice(index, 1);
                form.setFieldsValue({ products: prodList });
              }}
            >
              <Button size='small' type='text'>
                <Icon type='delete' />
              </Button>
            </PopoverConfirm>
          );
        },
      },
      {
        key: 'sort',
        align: 'center',
        title: '排序',
        width: 64,
        render() {
          return (
            <DragHandle>
              <Button size='small' type='text'>
                <Icon type='menu' />
              </Button>
            </DragHandle>
          );
        },
      },
      { dataIndex: 'productCode', title: '险种编码', width: 140 },
      { dataIndex: 'productName', title: '险种名称' },
      { dataIndex: ['productInsure', 'singleCoverage'], title: '保额', width: 140 },
      { dataIndex: ['productInsure', 'minCoverageLimit'], title: '最低保额', width: 140 },
      { dataIndex: ['productInsure', 'maxCoverageLimit'], title: '最高保额', width: 140 },
    ],
    [],
  );

  const dataSource = useFormValue(form, 'products');

  return (
    <>
      <FieldEffect name='products' initialValue={[]} />

      <Box>
        <SelectProduct selectType='checkbox' rowKey='productCode' companyCode={companyCode} onOk={onSelect}>
          <Button type='primary'>+ 新 增</Button>
        </SelectProduct>
        <Box py={2} />
      </Box>

      <DragAndDropProvider {...config}>
        <DroppableContainer>
          <Table dataSource={dataSource} columns={columns} size='middle' pagination={false} {...tableProps} />
        </DroppableContainer>
      </DragAndDropProvider>
    </>
  );
}

function AddPage({ history, location }) {
  const planBusinessCode = useQueryValue('planBusinessCode');
  const xhr = useReq(PlanAPI.getByCode);
  const saveXhr = useReq(PlanAPI.insertOrUpdate);
  const [form] = Form.useForm();

  useEffect(() => {
    if (planBusinessCode) {
      xhr.start(planBusinessCode).then((res) => {
        if (res.data) form.setFieldsValue(res.data);
      });
    }
  }, [planBusinessCode]);

  const context = useSimpleMemo({ form, planBusinessCode });

  const loading = [xhr.status, saveXhr.status].includes('loading');

  const handleSave = useCall(async () => {
    const values = await form.validateFields().catch(catchAndScrollFor(form));
    if (!values.products?.length) {
      message.warn('请至少添加一个险种');
      return false;
    }
    if (values.products.every((i) => i.productType !== MAIN_RISK_TYPE)) {
      message.warn('请至少选择一款主险');
      return false;
    }

    await saveXhr.start({ ...(xhr.result?.data ?? null), ...values });

    message.success('保存成功');
    history.replace(pathJoin(location.pathname, '../'));
  });

  return (
    <Context.Provider value={context}>
      <Spin spinning={loading}>
        <Form form={form}>
          <FormSection title='计划'>
            <FieldCols form={form} fields={FIELDS} />
          </FormSection>

          <FormSection title='险种'>
            <RequestProducts />
          </FormSection>
        </Form>

        <Box flex jus='center' py={3} className='form-page-btn'>
          <Space size='large'>
            <Button onClick={history.goBack}>返回</Button>
            <Button type='primary' onClick={handleSave}>
              保存
            </Button>
          </Space>
        </Box>
      </Spin>
    </Context.Provider>
  );
}

export default AddPage;
